#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#include<sys/wait.h>
//#include<fork.h>
#include<signal.h>

void catch_child(int signo)
{
    pid_t wpid;
    int status;
   // while(wpid=wait(NULL))//while循环方式回收子进程，避免出现僵尸进程
    while(wpid=waitpid(-1,status,0)!=-1)
    {
        if(WIFEXITED(status))
    
        printf("catch child id=%d,ret=%d\n",wpid,WEXITSTATUS(status));

        //wait 回收子进程
      //  printf("catch child id=%d\n",wpid);
    }
}

int main(void)
{

    //function attention: 实现对子进程回收给予信号
    pid_t pid;
    int i;
    //对SIGCHLD 设置阻塞
    sigset_t set;
    sigemptyset(&set);//防止子进程结束，父进程SIGCHLD的捕捉函数还未执行完
    sigaddset(&set,SIGCHLD);
    sigprocmask(SIG_BLOCK,&set,NULL); //设置pcb 的阻塞屏蔽集合


    for(int i=0;i<10;i++)
    {

        //循环创建10个子进程
        pid=fork();
        if(pid==0)
        {
            break;//避免子进程后续在创建新的子进程
        }

    }

    //在父进程中对结束的子进程进行回收
    if(10==i)
    {

        //父进程
        struct sigaction act,oldact;
        act.sa_handler=catch_child; //设置回调函数
        sigemptyset(&act.sa_mask);//设置回调（捕捉）函数执行期间的阻塞信号集
        act.sa_flags=0;
        sigaction(SIGCHLD,&act,&oldact);//注册回调函数
    
        //对SIGCHLD的信号解除阻塞
        sigprocmask(SIGCHLD,&set,NULL);
        printf("I am parent,pid=%d\n",getpid());

        while(1);//模拟父进程后续的动作
        
    }
    else
    { 
        //子进程执行的逻辑，结束后由父进程进行回收

//        sleep(3);
        printf("i am child,pid=%d\n",getpid());
        return i;        
    }
}

